<script lang="ts" setup>
import { computed, onMounted, ref, watch } from 'vue';

import { MdiLeft, MdiRight } from '@vben/icons';

import { Button } from 'ant-design-vue';
import dayjs, { Dayjs } from 'dayjs';

interface CalendarDay {
  date: Dayjs;
  isCurrentMonth: boolean;
  isToday: boolean;
  isWeekend: boolean;
  isPast: boolean;
}
const props = defineProps({
  // 选中的星期
  selectWeek: {
    type: Array,
    default: () => [],
  },
});
const emit = defineEmits(['change']);
// 选择的日期天数
const selectedDays = ref(0);
// 星期标题
const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const currentDate = ref<Dayjs>(dayjs());
const selectedDates = ref<Dayjs[]>([]);
const today = dayjs().startOf('day'); // 用于比较日期

// 计算显示的三个月
const displayMonths = computed<Dayjs[]>(() => {
  return [
    currentDate.value,
    currentDate.value.add(1, 'month'),
    currentDate.value.add(2, 'month'),
  ];
});

// 是否是当前月份
const isCurrentMonth = computed<boolean>(() => {
  return currentDate.value.isSame(dayjs(), 'month');
});

// 获取月份中的天数（只显示当前月份）
const getDaysInMonth = (month: Dayjs): CalendarDay[] => {
  const days: CalendarDay[] = [];
  const startOfMonth = month.startOf('month');
  const endOfMonth = month.endOf('month');

  // 计算第一周开始前的空白天数
  const startDayOfWeek = startOfMonth.day();

  // 添加空白占位符
  for (let i = 0; i < startDayOfWeek; i++) {
    days.push({
      date: startOfMonth.subtract(startDayOfWeek - i, 'day'),
      isCurrentMonth: false,
      isToday: false,
      isWeekend: false,
      isPast: false,
    });
  }

  // 填充当前月的日期
  for (let i = 1; i <= month.daysInMonth(); i++) {
    const date = startOfMonth.date(i);
    days.push({
      date,
      isCurrentMonth: true,
      isToday: date.isSame(today, 'day'),
      isWeekend: date.day() === 0 || date.day() === 6,
      isPast: date.isBefore(today, 'day'),
    });
  }

  // 确保日历有6行（42个格子）
  const totalCells = 42;
  const remainingDays = totalCells - days.length;

  // 在后面添加空白占位符
  for (let i = 0; i < remainingDays; i++) {
    days.push({
      date: endOfMonth.add(i + 1, 'day'),
      isCurrentMonth: false,
      isToday: false,
      isWeekend: false,
      isPast: false,
    });
  }

  return days;
};

// 将选中的日期数组格式化为字符串数组并抛出事件
const emitDatesChange = () => {
  // const formattedDates = selectedDates.value.map((date) =>
  //   date.format('YYYY-MM-DD'),
  // );
  // emit('change', formattedDates);
};

// 日期点击处理
const handleDayClick = (date: Dayjs, isCurrentMonth: boolean) => {
  if (!isCurrentMonth) return;

  const dateStr = date.format('YYYY-MM-DD');
  const index = selectedDates.value.findIndex(
    (d) => d.format('YYYY-MM-DD') === dateStr,
  );

  if (index === -1) {
    selectedDates.value.push(date);
  } else {
    selectedDates.value.splice(index, 1);
  }

  // 按日期排序
  selectedDates.value.sort((a, b) => a.diff(b));
  // 抛出事件给父组件
  emitDatesChange();
};

// 清空所有日期
const clearAll = () => {
  selectedDates.value = [];
  // 抛出事件给父组件
  emitDatesChange();
};

// 检查日期是否被选中
const isSelected = (date: Dayjs): boolean => {
  return selectedDates.value.some(
    (d) => d.format('YYYY-MM-DD') === date.format('YYYY-MM-DD'),
  );
};

// 切换上个月
const handlePrevMonth = () => {
  currentDate.value = currentDate.value.subtract(1, 'month');
};

// 切换下个月
const handleNextMonth = () => {
  currentDate.value = currentDate.value.add(1, 'month');
};

// 监听 selectedDates 和 selectWeek 的变化
watch(
  [selectedDates, () => props.selectWeek],
  () => {
    const validDates = selectedDates.value.filter((date) => {
      const dayOfWeek = date.day();
      return props.selectWeek.includes(dayOfWeek.toString());
    });
    selectedDays.value = validDates.length;
    const formattedDates = validDates.map((date) => date.format('YYYY-MM-DD'));
    emit('change', formattedDates);
  },
  { deep: true },
);

onMounted(() => {
  // 初始化时选择今天
  // handleDayClick(dayjs(), true);
});
</script>

<template>
  <div class="multi-month-calendar px-5 pt-3">
    <!-- 选中的日期 -->
    <div class="flex items-center">
      已选择
      <span class="text-primary mx-1">{{ selectedDays || 0 }}</span>
      天
      <Button class="ml-3 h-auto w-auto p-0" type="link" @click="clearAll">
        重置
      </Button>
    </div>
    <div class="relative">
      <!-- 月份切换控制 -->
      <div
        class="absolute left-0 top-0.5 flex w-full items-center justify-between"
      >
        <Button
          :disabled="isCurrentMonth"
          class="month-switch-btn w-auto px-0"
          type="text"
          @click="handlePrevMonth"
        >
          <MdiLeft class="text-3xl" />
        </Button>
        <Button
          class="month-switch-btn w-auto px-0"
          type="text"
          @click="handleNextMonth"
        >
          <MdiRight class="text-3xl" />
        </Button>
      </div>

      <!-- 三个月日历卡片 -->
      <div class="calendar-cards">
        <div
          v-for="(month, index) in displayMonths"
          :key="month.format('YYYY-MM')"
          :class="{
            'current-month': index === 0 && isCurrentMonth,
          }"
          class="calendar-card"
        >
          <div class="card-header py-2 text-center">
            {{ month.format('YYYY年MM月') }}
          </div>

          <div class="calendar-grid">
            <!-- 星期标题 -->
            <div v-for="day in weekDays" :key="day" class="week-day">
              {{ day }}
            </div>
            <!-- 日历日期 -->
            <div
              v-for="(day, dayIndex) in getDaysInMonth(month)"
              :key="dayIndex"
              :class="{
                selected: isSelected(day.date),
                weekend: day.isWeekend,
                disabled: day.isPast,
                empty: !day.isCurrentMonth,
              }"
              class="calendar-day"
              @click="
                !day.isPast && handleDayClick(day.date, day.isCurrentMonth)
              "
            >
              <div class="day-number">
                {{ day.isCurrentMonth ? day.date.date() : '' }}
                <span v-if="day.isToday" class="today-dot"></span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
.multi-month-calendar {
  width: 100%;
  max-width: 1000px;
}

.month-switch-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s;

  &:not(:disabled):hover {
    color: hsl(var(--primary));
    background: none;
  }

  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
}

.month-display {
  font-weight: 600;
  color: rgba(0, 0, 0, 0.85);
  min-width: 300px;
  text-align: center;
  padding: 0 10px;
}

.calendar-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 15px;
  margin-bottom: 24px;

  @media (max-width: 860px) {
    grid-template-columns: 1fr;
    max-width: 400px;
    margin: 0 auto;
  }
}

.calendar-card {
  overflow: hidden;
}

.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0px;
}

.week-day {
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;

  &:first-child,
  &:nth-child(7) {
    color: #ff4d4f;
  }
}

.calendar-day {
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  transition: all 0.2s;
  &.weekend:not(.empty):not(.disabled) {
    .day-number {
      color: #ff4d4f;
    }
  }
  &:hover:not(.empty):not(.disabled) {
    background: hsl(var(--primary) / 0.3);
    color: #ffffff;
  }

  &.selected:not(.disabled) {
    background: hsl(var(--primary));
    color: #ffffff;
    .day-number {
      color: #ffffff !important;
    }
  }

  // 空白格子样式
  &.empty {
    cursor: default;
    visibility: hidden;
  }

  // 禁用日期样式
  &.disabled {
    cursor: not-allowed;

    .day-number {
      opacity: 0.5;
    }

    &:hover {
      background: transparent;
      transform: none;
    }
  }
}

.day-number {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  transition: all 0.2s;
}
</style>
